import {
  Scene,
  PerspectiveCamera,
  WebGLRenderer,
  Mesh,
  PlaneGeometry,
  DirectionalLight,
  AmbientLight,
  MeshPhongMaterial,
  CylinderGeometry,
  ArrayCamera,
  Vector4,
} from 'three'

const AMOUNT = 6


export default class CameraArray {
  constructor(ele) {
    if (!(ele instanceof HTMLElement)) {
      throw new Error('第一个参数必须是dom')
    }

    this.scene = new Scene()
    this.camera = this.initCamera()
    // this.camera.position.z = 3

    this.renderer = this.initRenderer()
    // this.renderer.render(this.scene, this.camera)

    this.initLight()
    this.initBackground()
    this.mesh = this.initGeo()
    this.scene.add(this.mesh)

    ele.appendChild(this.renderer.domElement)

    this.animate()
    window.addEventListener('resize', this.onWindowResize.bind(this))
  }

  onWindowResize() {
    const ASPECT_RATIO = window.innerWidth / window.innerHeight
    const WIDTH = (window.innerWidth / AMOUNT) * window.devicePixelRatio
    const HEIGHT = (window.innerHeight / AMOUNT) * window.devicePixelRatio
    const camera = this.camera;
    camera.aspect = ASPECT_RATIO;
    camera.updateProjectionMatrix();
    for (let y = 0; y < AMOUNT; y++) {
      for (let x = 0; x < AMOUNT; x++) {
        const subcamera = camera.cameras[AMOUNT * y + x]

        subcamera.viewport.set(
          Math.floor(x * WIDTH),
          Math.floor(y * HEIGHT),
          Math.ceil(WIDTH),
          Math.ceil(HEIGHT)
        )

        subcamera.aspect = ASPECT_RATIO
        subcamera.updateProjectionMatrix()
      }
    }

    this.renderer.setSize(window.innerWidth, window.innerHeight)
  }

  initCamera() {
    const ASPECT_RATIO = window.innerWidth / window.innerHeight
    const WIDTH = (window.innerWidth / AMOUNT) * window.devicePixelRatio
    const HEIGHT = (window.innerHeight / AMOUNT) * window.devicePixelRatio
    const cameras = []
    for (let y = 0; y < AMOUNT; y++) {
      for (let x = 0; x < AMOUNT; x++) {
        const subcamera = new PerspectiveCamera(40, ASPECT_RATIO, 0.1, 10)
        subcamera.viewport = new Vector4(
          Math.floor(x * WIDTH),
          Math.floor(y * HEIGHT),
          Math.ceil(WIDTH),
          Math.ceil(HEIGHT)
        )
        subcamera.position.x = x / AMOUNT - 0.5
        subcamera.position.y = 0.5 - y / AMOUNT
        subcamera.position.z = 1.5
        subcamera.position.multiplyScalar(2)
        subcamera.lookAt(0, 0, 0)
        subcamera.updateMatrixWorld()
        cameras.push(subcamera)
      }
    }
    return new ArrayCamera(cameras)
  }

  initRenderer() {
    const renderer = new WebGLRenderer()
    renderer.setSize(window.innerWidth, window.innerHeight)
    renderer.setPixelRatio(window.devicePixelRatio)
    renderer.shadowMap.enabled = true
    return renderer
  }

  initLight() {
    // 添加环境光
    this.scene.add(new AmbientLight(0x222244))
    // 添加平行光
    const light = new DirectionalLight()
    light.position.set(5, 5, 10)
    light.castShadow = true //开启阴影
    light.shadow.camera.zoom = 6
    this.scene.add(light)
  }

  initBackground() {
    const geoBackground = new PlaneGeometry(100, 100)
    const materialBackground = new MeshPhongMaterial({ color: 0x000066 })
    const background = new Mesh(geoBackground, materialBackground)
    background.receiveShadow = true
    background.position.set(0, 0, -1)
    this.scene.add(background)
  }

  initGeo() {
    const geo = new CylinderGeometry(0.5, 0.5, 1, 32)
    const mer = new MeshPhongMaterial({ color: 0xff0000 })
    const mesh = new Mesh(geo, mer)
    mesh.castShadow = true
    mesh.receiveShadow = true
    return mesh
  }

  animate() {
    requestAnimationFrame(() => this.animate.call(this))

    this.mesh.rotation.x += 0.005
    this.mesh.rotation.z += 0.005

    this.renderer.render(this.scene, this.camera)
  }
}